package org.jpush.impl.xml;

import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.jpush.packages.AnalyticsProtocol;
import org.jpush.packages.IncomingPacket;
import org.jpush.packages.OutgoingPacket;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class XMLPacket implements IncomingPacket, OutgoingPacket
{
	private static DocumentBuilder documentBuilder;
	
	static
	{
		try
		{
			documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
		}
		catch (ParserConfigurationException e)
		{
			// TODO Auto-generated catch block
			throw new RuntimeException(e);
		}
	}

	private Document document;
	private Element xmlRoot;
	private String data;
	private  boolean isXmlFormat;

	public XMLPacket(AnalyticsProtocol typeId)
	{
		document = documentBuilder.newDocument();
	    xmlRoot = document.createElement("root");
	    document.appendChild(xmlRoot);

        xmlRoot.setAttribute("typeId", Integer.toString(typeId.ordinal()));
        isXmlFormat = true;
    }

	public XMLPacket(String data)
    {
        isXmlFormat = false;
        this.data = data;
    }

	public XMLPacket()
    {
    }


	public AnalyticsProtocol getTypeId()
    {
        if(xmlRoot.hasAttributes())
            return AnalyticsProtocol.None;;
        String val = xmlRoot.getAttribute("typeId");
        if(val != null)
        {
            //return atoi(val);
        	int value = Integer.valueOf(val);
        	return AnalyticsProtocol.values()[value];
        }

        return AnalyticsProtocol.None;
    }


	public Element getRoot()
    {
        return xmlRoot;
    }

	public boolean encode()
    {
        if (!isXmlFormat)
            return true;

        if (!xmlRoot.hasAttributes())
            return false;

        data = document.toString();

//        delete [] pString;
        return true;
    }


	public boolean decode(String data)
    {
		Document document = null;
		try
		{
			document = documentBuilder.parse(data);
		}
		catch (SAXException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		catch (IOException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		if (document == null)
			return false;

		NodeList nodeList = document.getChildNodes();
		if (nodeList == null || nodeList.getLength() != 1)
			return false;
		
        Node node = nodeList.item(0);
        if (node instanceof Element)
        {
        	Element xmlRoot = (Element)node;
        	if ("root".equals(xmlRoot.getNodeName()) && xmlRoot.hasAttributes())
        	{
                this.xmlRoot = xmlRoot;
                this.document = document;
                this.isXmlFormat = true;
                
                return true;
        	}
        }
        return false;
    }


	public String getArgumentAsText(String argName)
    {
		if (!xmlRoot.hasAttributes())
			return "";
        String val = xmlRoot.getAttribute(argName);
        if (val == null)
            return "";
        return val;
    }

	public int getArgumentAsInt(String argName)
    {
		return Integer.parseInt(getArgumentAsText(argName));
    }

	public boolean getArgumentAsBool(String argName)
    {
		return Boolean.parseBoolean(getArgumentAsText(argName));
    }

	public void setArgumentAsText(String argName, String val)
    {
        if (xmlRoot.hasAttributes())
            return;
        xmlRoot.setAttribute(argName, val);
    }

	public void setArgumentAsInt(String argName, int val)
    {
        setArgumentAsText(argName, Integer.toString(val));
    }

	public void setArgumentAsBool(String argName, boolean val)
    {
        setArgumentAsText(argName, Boolean.toString(val));
    }


	public String getData()
    {
        return data;
    }
}
